{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "title: ♾️伪随机数发生器\n",
    "password: \"\"\n",
    "tags:\n",
    "  - 密码学\n",
    "  - 概率论\n",
    "katex: false\n",
    "comments: true\n",
    "aside: true\n",
    "date: 2022-07-01 00:59:59\n",
    "cover: https://pan.weidows.tech/d/local/blog/ZMd92o.jpg\n",
    "top_img:\n",
    "---\n",
    "<!--\n",
    " * @?: *********************************************************************\n",
    " * @Author: Weidows\n",
    " * @LastEditors: Weidows\n",
    " * @LastEditTime: 2022-04-20 23:11:24\n",
    " * @FilePath: \\Blog-private\\scaffolds\\post.md\n",
    " * @Description:\n",
    " * @!: *********************************************************************\n",
    "-->\n",
    "\n",
    "## 序\n",
    "\n",
    "此发生器基于空间数组, 随机种子来自于 time 时间戳末尾位\n",
    "\n",
    "随着 random 次数增加, array 不确定度持续`叠加`, 每位概率会有一定波动但不会出现偏倚或黑洞\n",
    "\n",
    "熵来自于每次 update 的位置和次序, 淡化了某时刻 timestamp 和算力的影响\n",
    "\n",
    "思想类似卷积, 把过去与当前状态持续叠加到对未来的影响中\n",
    "\n",
    "- 现有缺陷\n",
    "\n",
    "  1. 无法保证 `恒定的概率` 或者说 `等概率随机`, 但可以近似做到 `自然随机`\n",
    "  2. array 需要预热, 预热效果也会影响一定范围内的随机数质量\n",
    "  3. 小批量随机效果贼差\n",
    "\n",
    "<a>![分割线](https://cdn.jsdelivr.net/gh/Weidows/Weidows/image/divider.png)</a>\n",
    "\n",
    "## 代码\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1K 个随机数 0-9 平均概率:\n",
      "[0.0, 0.0, 0.0, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]\n",
      "\n",
      "1M 个随机数 0-9 平均概率:\n",
      "[0.0, 0.0, 0.0, 1e-05, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
      "[0.08707, 0.09659, 0.07117, 0.09658, 0.08152, 0.11249, 0.08783, 0.15348, 0.07114, 0.14213]\n",
      "[0.07329, 0.09794, 0.08054, 0.11958, 0.08392, 0.09796, 0.07334, 0.10519, 0.08776, 0.18048]\n",
      "[0.11594, 0.10057, 0.09201, 0.12211, 0.05934, 0.10781, 0.05929, 0.10423, 0.08083, 0.15787]\n",
      "[0.11348, 0.09361, 0.09942, 0.09361, 0.08974, 0.11739, 0.1132, 0.09622, 0.08972, 0.09361]\n",
      "[0.09697, 0.08811, 0.07557, 0.13141, 0.0873, 0.10951, 0.07558, 0.08811, 0.09013, 0.15731]\n",
      "[0.09858, 0.07631, 0.11606, 0.07633, 0.13287, 0.07633, 0.09857, 0.09382, 0.1125, 0.11863]\n",
      "[0.07433, 0.12053, 0.07844, 0.11426, 0.07381, 0.11784, 0.09136, 0.12198, 0.09004, 0.11741]\n",
      "[0.07852, 0.09592, 0.11335, 0.12832, 0.0749, 0.09957, 0.07491, 0.12733, 0.07851, 0.12867]\n",
      "[0.07114, 0.11785, 0.08166, 0.15484, 0.06758, 0.11358, 0.06757, 0.12409, 0.09167, 0.11002]\n"
     ]
    }
   ],
   "source": [
    "from datetime import datetime\n",
    "\n",
    "array = [i for i in range(10)]\n",
    "\n",
    "\n",
    "def random():\n",
    "    time_str = str(datetime.now().timestamp())\n",
    "    if len(time_str) == 16: index = 0\n",
    "    else:\n",
    "        index = int(time_str[-1])\n",
    "\n",
    "    # core: 每次 random, 使 index 位加上下一位的数字\n",
    "    array[index] = (array[index] + array[(1 + index) % len(array)]) % 10\n",
    "\n",
    "    return array[index]\n",
    "\n",
    "\n",
    "def measure(random_times):\n",
    "    times = [0 for _ in range(10)]\n",
    "    for i in range(random_times):\n",
    "        num = random()\n",
    "        times[num] += 1\n",
    "\n",
    "        random_times_div_10 = random_times // 10\n",
    "        if i % random_times_div_10 == 0:\n",
    "            for i in range(10):\n",
    "                times[i] = times[i] / random_times_div_10\n",
    "            print(times)\n",
    "            times = [0 for _ in range(10)]\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    # print(random())\n",
    "\n",
    "    # 数量太小, 算力太大把随机度给淹了\n",
    "    print(\"1K 个随机数 0-9 平均概率:\")\n",
    "    measure(1_000)\n",
    "\n",
    "    print()\n",
    "\n",
    "    print(\"1M 个随机数 0-9 平均概率:\")\n",
    "    measure(1_000_000)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a>![分割线](https://cdn.jsdelivr.net/gh/Weidows/Weidows/image/divider.png)</a>\n",
    "\n",
    "## 位运算数值分布\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "XOR:\n",
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "[1, 0, 3, 2, 5, 4, 7, 6, 9, 8]\n",
      "[2, 3, 0, 1, 6, 7, 4, 5, 10, 11]\n",
      "[3, 2, 1, 0, 7, 6, 5, 4, 11, 10]\n",
      "[4, 5, 6, 7, 0, 1, 2, 3, 12, 13]\n",
      "[5, 4, 7, 6, 1, 0, 3, 2, 13, 12]\n",
      "[6, 7, 4, 5, 2, 3, 0, 1, 14, 15]\n",
      "[7, 6, 5, 4, 3, 2, 1, 0, 15, 14]\n",
      "[8, 9, 10, 11, 12, 13, 14, 15, 0, 1]\n",
      "[9, 8, 11, 10, 13, 12, 15, 14, 1, 0]\n",
      "OR:\n",
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
      "[1, 1, 3, 3, 5, 5, 7, 7, 9, 9]\n",
      "[2, 3, 2, 3, 6, 7, 6, 7, 10, 11]\n",
      "[3, 3, 3, 3, 7, 7, 7, 7, 11, 11]\n",
      "[4, 5, 6, 7, 4, 5, 6, 7, 12, 13]\n",
      "[5, 5, 7, 7, 5, 5, 7, 7, 13, 13]\n",
      "[6, 7, 6, 7, 6, 7, 6, 7, 14, 15]\n",
      "[7, 7, 7, 7, 7, 7, 7, 7, 15, 15]\n",
      "[8, 9, 10, 11, 12, 13, 14, 15, 8, 9]\n",
      "[9, 9, 11, 11, 13, 13, 15, 15, 9, 9]\n",
      "AND:\n",
      "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
      "[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]\n",
      "[0, 0, 2, 2, 0, 0, 2, 2, 0, 0]\n",
      "[0, 1, 2, 3, 0, 1, 2, 3, 0, 1]\n",
      "[0, 0, 0, 0, 4, 4, 4, 4, 0, 0]\n",
      "[0, 1, 0, 1, 4, 5, 4, 5, 0, 1]\n",
      "[0, 0, 2, 2, 4, 4, 6, 6, 0, 0]\n",
      "[0, 1, 2, 3, 4, 5, 6, 7, 0, 1]\n",
      "[0, 0, 0, 0, 0, 0, 0, 0, 8, 8]\n",
      "[0, 1, 0, 1, 0, 1, 0, 1, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "print(\"XOR:\")\n",
    "for i in range(10):\n",
    "    arr = []\n",
    "\n",
    "    for j in range(10):\n",
    "        arr.append(j ^ i)\n",
    "\n",
    "    print(arr)\n",
    "\n",
    "print(\"OR:\")\n",
    "for i in range(10):\n",
    "    arr = []\n",
    "\n",
    "    for j in range(10):\n",
    "        arr.append(j | i)\n",
    "\n",
    "    print(arr)\n",
    "# 产生 '7' 黑洞 (array 内都是 7)\n",
    "# 10M 个随机数 0-9 平均概率:\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 1e-06, 0.0, 0.0, 0.0, 0.0]\n",
    "# [0.0, 1.6e-05, 0.0, 0.035234, 0.0, 6e-06, 0.0, 0.933694, 0.0, 0.03105]\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]\n",
    "\n",
    "print(\"AND:\")\n",
    "for i in range(10):\n",
    "    arr = []\n",
    "\n",
    "    for j in range(10):\n",
    "        arr.append(j & i)\n",
    "\n",
    "    print(arr)\n",
    "# 产生 '0' 黑洞 (array 内都是 0)\n",
    "# 10M 个随机数 0-9 平均概率:\n",
    "# [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1e-06, 0.0, 0.0, 0.0]\n",
    "# [0.992248, 0.0, 0.002597, 0.0, 0.000949, 0.0, 0.001722, 0.0, 0.002484, 0.0]\n",
    "# [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
    "# [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
    "# [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
    "# [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
    "# [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
    "# [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
    "# [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]\n",
    "# [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a>![分割线](https://cdn.jsdelivr.net/gh/Weidows/Weidows/image/divider.png)</a>\n",
    "\n",
    "## golang-验证码-随机数生成\n",
    "\n",
    "最好不要用 rand.intn(), 位数太大时会溢出, 可以用递归来生成无限长的随机数 <sup id='cite_ref-1'>[\\[1\\]](#cite_note-1)</sup>\n",
    "\n",
    "```go\n",
    "func GetRandNum(digit int) (res string) {\n",
    "\tif digit < 1 {\n",
    "\t\treturn \"\"\n",
    "\t}\n",
    "\tif digit < 10 {\n",
    "\t\t// int32 封顶 2^9, 2^10 会溢出\n",
    "\t\tnum := rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(int32(Pow10(digit)))\n",
    "\t\tres = fmt.Sprintf(\"%0\"+strconv.Itoa(digit)+\"v\", num)\n",
    "\t} else {\n",
    "\t\tnum := rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(int32(Pow10(9)))\n",
    "\t\tres = fmt.Sprintf(\"%09v\", num) + GetRandNum(digit-9)\n",
    "\t}\n",
    "\treturn\n",
    "}\n",
    "\n",
    "func GetVerifyCode() string {\n",
    "\treturn GetRandNum(6)\n",
    "}\n",
    "```\n",
    "\n",
    "## 借物表\n",
    "\n",
    "<a name='cite_note-1' href='#cite_ref-1'>[1]</a>: [Golang/rand.go at master · Weidows/Golang](https://github.com/Weidows/Golang/blob/master/utils/rand.go)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.9.12 64-bit (system)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "8faf7328610876523a4e724188f9f8e34266025c0876869ab11d11b1ec3b5644"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
